package xyz.wbsite.screen.client;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.log.StaticLog;
import com.melloware.jintellitype.HotkeyListener;
import com.melloware.jintellitype.JIntellitype;
import me.friwi.jcefmaven.CefAppBuilder;
import me.friwi.jcefmaven.CefBuildInfo;
import me.friwi.jcefmaven.CefInitializationException;
import me.friwi.jcefmaven.MavenCefAppHandlerAdapter;
import me.friwi.jcefmaven.UnsupportedPlatformException;
import org.cef.CefApp;
import org.cef.CefClient;
import org.cef.browser.CefBrowser;

import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusListener;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;

public class WebClient extends JFrame {

    // 退出
    private final int KEY_MARK_ESC = 1;
    // 最小化
    private final int KEY_MARK_SWITCH = 2;
    // 刷新
    private final int KEY_MARK_RELOAD = 3;
    // 添加自启
    private final int KEY_MARK_SET_START = 4;
    // 移除自启
    private final int KEY_MARK_DEL_START = 5;

    private CefClient cefClient;
    private CefApp cefApp;
    private CefBrowser cefBrowser;
    private String lastUrl = "about:blank";
    private Properties config;

    private final HotkeyListener hotkeyListener = new HotkeyListener() {
        @Override
        public void onHotKey(int i) {
            switch (i) {
                case KEY_MARK_ESC: {
                    StaticLog.info("exit.");
                    JIntellitype.getInstance().unregisterHotKey(KEY_MARK_ESC);
                    JIntellitype.getInstance().removeHotKeyListener(hotkeyListener);
                    close();
                }
                break;
                case KEY_MARK_SWITCH: {
                    StaticLog.info("screen switch.");
                    if (getExtendedState() == Frame.NORMAL) {
                        removeNotify();
                        setUndecorated(true);
                        setExtendedState(JFrame.MAXIMIZED_BOTH);
                    } else {
                        setExtendedState(Frame.NORMAL);
                        removeNotify();
                        setUndecorated(false);
                    }
                    setVisible(true);
                }
                break;
                case KEY_MARK_RELOAD: {
                    StaticLog.info("screen reload.");
                    reload();
                }
                break;
                case KEY_MARK_SET_START: {
                    StaticLog.info("screen setStartup.");
                    setStartup();
                }
                break;
                case KEY_MARK_DEL_START: {
                    StaticLog.info("screen delStartup.");
                    delStartup();
                }
                break;
            }
        }
    };

    public WebClient(Properties config) {
        this.config = config;
        try {
            initCef(new String[]{});
            initClient();
        } catch (Exception e) {
            StaticLog.error(e);
        }
    }

    private void initClient() {
        setTitle(getProp("title", "ScreenClient"));
        getContentPane().add(cefBrowser.getUIComponent(), BorderLayout.CENTER);
        setSize(800, 600);//初始大小
        setLocation(0, 0);//位置
        // 设置全屏模式
        if ("full".equals(getProp("size", "full"))) {
            setExtendedState(JFrame.MAXIMIZED_BOTH);
            setUndecorated(true);
            setAlwaysOnTop(true);
        }

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                // 关闭应用时要释放资源
                CefApp.getInstance().dispose();
                dispose();
                System.exit(0);//0正常退出，1非正常退出
            }
        });

        // 添加热键
        JIntellitype.getInstance().registerHotKey(KEY_MARK_ESC, 0, KeyEnum.ESC.value());
        JIntellitype.getInstance().registerHotKey(KEY_MARK_SET_START, 0, KeyEnum.F1.value());
        JIntellitype.getInstance().registerHotKey(KEY_MARK_DEL_START, 0, KeyEnum.F2.value());
        JIntellitype.getInstance().registerHotKey(KEY_MARK_RELOAD, 0, KeyEnum.F5.value());
        JIntellitype.getInstance().registerHotKey(KEY_MARK_SWITCH, 0, KeyEnum.F11.value());
        JIntellitype.getInstance().addHotKeyListener(hotkeyListener);

        //设置图标
        URL resource = ResourceUtil.getResource("ScreenClient.png");
        BufferedImage read = ImgUtil.read(resource);
        setIconImage(read);

        // 显示
        setVisible(true);
    }

    /**
     * 初始化 CefBrowser
     *
     * @param args
     */
    private void initCef(String[] args) throws InterruptedException, UnsupportedPlatformException, CefInitializationException, IOException {
        CefAppBuilder builder = new CefAppBuilder();
        // window下不需要OSR
        boolean useOSR = false;
        builder.getCefSettings().windowless_rendering_enabled = useOSR;
        builder.setAppHandler(new MavenCefAppHandlerAdapter() {
            @Override
            public void stateHasChanged(org.cef.CefApp.CefAppState state) {
                // 关闭应用时退出jvm运行
                if (state == CefApp.CefAppState.TERMINATED) System.exit(0);
            }
        });

        // 设置cef运行参数，这里为空
        builder.addJcefArgs(args);

        // 这边不设置，程序会自动解压
        // 设置 cef chrome实例的目录，关键，若不设置他会默认从网络中下载，国外网络可能下载不稳定导致失败
        // 我的 cef chrome 位于项目的chrome目录下 C:\Users\Administrator\Desktop\project\java\demo-desktop\chrome
        // builder.setInstallDir(new File(System.getProperty("user.dir") + File.separator + "chrome"));
        // 由于是手动设置cef的chrome，我们要跳过ins检查，防止版本不一致导致从镜像站下载
        // builder.setSkipInstallation(true);

        // 全局的 CefApp 每个程序只能有一个，线程安全
        cefApp = builder.build();
        // 显示一些版本信息
        CefBuildInfo buildInfo = CefBuildInfo.fromClasspath();
        StaticLog.info(buildInfo.toString());
        CefApp.CefVersion cefVersion = cefApp.getVersion();
        StaticLog.info(cefVersion.toString());

        // 创建一个浏览器客户端实例
        cefClient = cefApp.createClient();

        // 创建一个浏览器实例
        lastUrl = getProp("url", "html/index.html");
        // 处理非http时的相对路径
        if (!lastUrl.startsWith("http")) {
            lastUrl = new File(lastUrl).getAbsolutePath();
        }

        cefBrowser = cefClient.createBrowser(lastUrl, useOSR, true);
    }

    /**
     * 加载地址
     *
     * @param url 地址
     * @throws InterruptedException
     */
    public void loadUrl(String url) throws InterruptedException {
        // 必须延迟，否则可能因为切换太快无法加载成功
        Thread.sleep(300);
        lastUrl = url;
        // 处理非http时的相对路径
        if (!lastUrl.startsWith("http")) {
            lastUrl = new File(lastUrl).getAbsolutePath();
        }
        cefBrowser.loadURL(url);
    }

    /**
     * 刷新
     */
    public void reload() {
        // 创建一个浏览器实例
        cefBrowser = cefClient.createBrowser(lastUrl, false, true);
        getContentPane().remove(0);
        getContentPane().add(cefBrowser.getUIComponent(), BorderLayout.CENTER);
        setVisible(true);
    }

    /**
     * 开机自启
     */
    public void setStartup() {
        if (ShortCutUtil.setStartup(new File("ScreenClient.exe"))) {
            executeJavaScript("alert('set startup success')");
        } else {
            executeJavaScript("alert('set startup failed')");
        }
    }

    /**
     * 删除自启
     */
    public void delStartup() {
        if (ShortCutUtil.delStartup(new File("ScreenClient.exe"))) {
            executeJavaScript("alert('del startup success')");
        } else {
            executeJavaScript("alert('del startup failed')");
        }
    }

    private String getProp(String key, String defaultValue) {
        return Convert.toStr(config.getProperty(key), defaultValue);
    }

    public void addFocusListener(FocusListener listener) {
        cefBrowser.getUIComponent().addFocusListener(listener);
    }

    public void addMouseListener(MouseListener listener) {
        cefBrowser.getUIComponent().addMouseListener(listener);
    }

    public void addKeyListener(KeyListener listener) {
        cefBrowser.getUIComponent().addKeyListener(listener);
    }

    public void executeJavaScript(String javascript) {
        cefBrowser.executeJavaScript(javascript, null, 1);
    }

    public void close() {
        // 关闭应用时要释放资源
        CefApp.getInstance().dispose();
        dispose();
        System.exit(0);
    }
}
